2.15 Die For ... Each-Schleife
 
In diesem Zusammenhang ist eine weitere Schleifenform interessant und wichtig - die For ... Each-Schleife. Sie ist mit der For ... Next-Schleife vergleichbar. Diesmal zählt allerdings keine Variable hoch, sondern die Schleife greift auf alle Elemente einer Sammlung zu.
Das könnte dann wie folgt aussehen:
Dim lstElement as Object
For Each lstElement In lstListe.Items
MessageBox.Show(Ctype(lstElement, String))
Next
lstListe.Items ist die Sammlung der Einträge; auf jedes einzelne lstElement kann zugegriffen werden. Damit der Inhalt angezeigt werden kann, muss das Objekt erst mit der Funktion CType umgewandelt werden. Analog funktioniert dies bei einem Formular. Auf ihm sitzen mehrere Steuerelemente. Will man mit einer Schleife auf alle zugreifen, dann beispielsweise so:
Dim ctl As System.Windows.Forms.Control
Dim strAnzeige As String
For Each ctl in Me.Controls
strAnzeige &= vbCr & ctl.Name
Next
MessageBox.Show(ctl.Name)
Natürlich könnte man auch deklarieren:
Dim ctl As Object
Abbildung 2.32
Die Liste der Steuerelemente auf dem Formular
Und nun sollen alle ausgewählten Einträge angezeigt werden. Hierzu wird eine Schleife benötigt. Dabei hilft die Sammlung SelectedItems:
Dim lstElement As Object
Dim strListe As String
For Each lstElement In lstListe.SelectedItems
strListe &= vbCr & CType(lstElement, String)
Next
MessageBox.Show(strListe)
Wer den Zugriff über Objektvariablen nicht mag oder sich damit schwer tut, der kann die Schleife auch »klassisch« als Zählerschleife gestalten:
Dim intZähler As Integer
For intZähler = 0 To _
Me.lstListe.SelectedItems.Count - 1
strListe &= vbCr & Me.lstListe.SelectedItems(intZähler)
Next
MessageBox.Show(strListe)
Auf den ersten Blick erstaunlich gestaltet sich die Lösung des nächsten Problems: Der Benutzer soll per »Knopfdruck« einen oder mehrere Einträge löschen. Bei einer Einzelauswahl wäre dies kein Problem. Dort kann aus der Sammlung der Items der markierte Eintrag gelöscht werden:
Me.lstListe.Items.Remove(Me.lstListe.SelectedItem)
Lässt man allerdings eine Zählerschleife über die Items laufen, dann könnte man sie löschen, oder?
Dim intZähler As Integer
For intZähler = 0 To _
Me.lstListe.SelectedItems.Count - 1
Me.lstListe.Items.Remove _
(Me.lstListe.SelectedItems(intZähler))
Next
Ein Test zeigt, dass zwar ein markiertes Element gelöscht wird, allerdings kommt es bei mehreren zu einer Fehlermeldung. Was passiert? Bei zwei markierten Einträgen wird zuerst die Nummer 0 gelöscht. Danach wird der Zähler auf 1 gesetzt. Nun wird die Nummer 1 gelöscht; allerdings ist sie nun aufgerückt und hat den Platz 1 (Nummer 0) eingenommen. Somit kann eine Nummer 1 nicht mehr gefunden werden.
Abbildung 2.33
Mehrere Einträge können gelöscht werden.
Es gibt mehrere Lösungen für dieses Problem. Man könnte jedes Mal die Nummer 0 löschen. Oder man lässt die Schleife vom letzten zum ersten Item laufen:
Dim intZähler As Integer
For intZähler = Me.lstListe.SelectedItems _
.Count - 1 To 0 Step -1
Me.lstListe.Items.Remove _
(Me.lstListe.SelectedItems(intZähler))
Next
Das Löschen der gesamten Liste ist einfach:
Me.lstListe.Items.Clear
Nun sollen sich neben der Liste noch zwei Buttons befinden, mit deren Hilfe vorhandene Einträge nach oben, beziehungsweise nach unten geschoben werden. Ein Eintrag könnte folgendermaßen gelöscht und verschoben werden:
Dim intPos As Integer
Dim objEintrag As Object
objEintrag = Me.lstListe.SelectedItem
intPos = Me.lstListe.SelectedIndex
Me.lstListe.Items.Remove(objEintrag)
Me.lstListe.Items.Insert(intPos - 1, _
objEintrag)
Natürlich könnte man es auch ohne Variablen schreiben, aber der Code würde schnell unübersichtlich werden.
Und wenn man eine Schleife darum baut (und ein klein wenig den Code ändert), dann kann man alle markierten Einträge um eine Position nach oben verschieben:
Dim intZähler As Integer
Dim intPos As Integer
Dim objEintrag As Object
For intZähler = 0 To _
Me.lstListe.SelectedItems.Count - 1
objEintrag = Me.lstListe.SelectedItem
intPos = Me.lstListe.Items.IndexOf _
(Me.lstListe.SelectedItem)
Me.lstListe.Items.Remove(objEintrag)
Me.lstListe.Items.Insert(intPos - 1, _
objEintrag)
Next
Abbildung 2.34
Duplo und Mars sind zwischen Gummibärchen und Lutscher.
Abbildung 2.35
Sie werden um eine Position nach oben verschoben.
Der geneigte Leser darf sich gerne daran versuchen, wie man die markierten Einträge nach unten verschieben kann. Ein Tipp: Es müssen zwei Kleinigkeiten verändert werden.
Allerdings wird ein Fehler gemeldet, wenn der Benutzer den ersten Eintrag ausgewählt hat. Dies sollte man überprüfen. Mit einem einfachen Trick kann auf die Schleife verzichtet werden. SelectedItem gibt bei einer Mehrfachauswahl immer den obersten Eintrag zurück. Und bei diesem kann überprüft werden, ob er die Nummer 0 besitzt:
If Me.lstListe.Items.IndexOf _
(Me.lstListe.SelectedItem) = 0 Then
MessageBox.Show("Geht nicht")
Exit Sub
End If
Damit der Benutzer nicht ständig Fehlermeldungen um die Ohren geschlagen bekommt, kann man ihm dadurch helfen, dass ein Verschieben nach oben nicht mehr möglich ist, wenn einer der markierten Einträge der erste ist. Das zugehörige Objekt ist die Liste, das Ereignis lautet SelectedIndexChanged.
Abbildung 2.36
Das Verschieben nach oben ist nicht mehr möglich.
Private Sub lstListe_SelectedIndexChanged _
(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles _
lstListe.SelectedIndexChanged
If Me.lstListe.SelectedItems.Count > 0 Then
If Me.lstListe.Items.IndexOf _
(Me.lstListe.SelectedItem) = 0 Then
Me.butNachOben.Enabled = False
Else
Me.butNachOben.Enabled = True
End If
End If
End Sub
Etwas schwieriger ist das Ausschalten des Buttons »NachUnten«, wenn bei einer Mehrfachauswahl der letzte Eintrag ausgewählt wurde. Über die Variable intPosLetzte wird die Position des letzten markierten Eintrags ermittelt. Stimmt diese Zahl mit der Anzahl der Einträge der Liste überein, dann wird der Button »NachUnten« deaktiviert:
Dim intPosLetzte As Integer
intPosLetzte = lstListe.Items.IndexOf
(lstListe.SelectedItems(lstListe.SelectedItems.Count - 1))
If intPosLetzte = lstListe.Items.Count - 1 Then
butNachUnten.Enabled = False
Else
butNachUnten.Enabled = True
End If
...
Abbildung 2.37
Nun kann nichts mehr nach unten verschoben werden.
|